package com.yinxing.webapi.shiro;

import com.yinxing.webapi.code.entity.sys.SysUser;
import com.yinxing.webapi.code.service.sys.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class LoginRealm extends AuthorizingRealm {

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    @Autowired
    private ISysUserService sysUserService;

    /**
     * 获取当前用户角色与权限信息
     * @param principals 当前登录账户
     * @return AuthorizationInfo 封装了角色与权限数据对象
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        LoginUser loginUser = (LoginUser) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo account = new SimpleAuthorizationInfo();
        //用户角色编码集合注册到shiro中
        account.addRoles(loginUser.getRoles());
        //用户权限编码集合注册到shiro中
        account.addStringPermissions(loginUser.getPermissions());
        return account;
    }

    /**
     * 用户登录严重
     * @param token 封装了用户名密码
     * @return AuthenticationInfo 登录成功.返回当前用户对象数据结构
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken loginToken = (UsernamePasswordToken) token;
        String username = loginToken.getUsername();
        String password = new String(loginToken.getPassword());

        //根据登录账户名查询用户数据
        SysUser sysUser = sysUserService.selectByLoginName(username);
        if (sysUser == null) {
            throw new AuthenticationException(String.format("登录用户名{%s}查询不到用户信息", username));
        }

        //启用|禁用状态检查
        if(sysUser.getStop_()) {
            throw new LockedAccountException(String.format("当前账户{%s}已被管理员禁用", username));
        }

        //盐+输入明文密码 计算出数据库中的密码
        String inputPassword = DigestUtils.md5Hex(sysUser.getSalt_() + password);
        if (!sysUser.getPassword_().equals(inputPassword)) {
            throw new AuthenticationException(String.format("输入密码{%s}不正确", password));
        }

        //创建登录账户信息
        LoginUser loginUser = sysUserService.createloginUser(sysUser.getId_(), loginToken.getHost());

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginUser, password, getName());
        log.info("账户登录成功:{{}}", loginUser);
        return info;
    }

}
